package com.hnas.trade.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.hnas.account.orm.Account;
import com.hnas.account.service.AccountService;
import com.hnas.account.util.AccountConstant;
import com.hnas.api.domain.ResultCode;
import com.hnas.api.dto.DTOResult;
import com.hnas.common.domain.CoreTradeType;
import com.hnas.common.util.CommonUtils;
import com.hnas.core.util.DateUtil;
import com.hnas.core.util.StringUtil;
import com.hnas.ecard.orm.AccECard;
import com.hnas.ecard.orm.CardTrail;
import com.hnas.ecard.service.AccECardService;
import com.hnas.ecard.service.CardTrailService;
import com.hnas.hnt.orm.HntEmployeeCard;
import com.hnas.hnt.service.HntEmployeeCardService;
import com.hnas.hnt.service.IMrchService;
import com.hnas.trade.dao.TradeRecordDao;
import com.hnas.trade.domain.OrderStatus;
import com.hnas.trade.domain.OrderType;
import com.hnas.trade.domain.PayStatus;
import com.hnas.trade.domain.TradeType;
import com.hnas.trade.domain.TranState;
import com.hnas.trade.orm.AbnormalOrder;
import com.hnas.trade.orm.TradeRecord;
import com.hnas.trade.service.AbnormalOrderService;
import com.hnas.trade.service.OrderService;
import com.hnas.trade.service.TradeRecordService;
import com.hnas.trade.service.UpdateCoreTradeTaskService;
import com.hnas.trade.service.dto.DTOOrder;
import com.hnas.trade.service.dto.DTOResultTransApp;
import com.hnas.trade.service.dto.DTOSearchTrans;
import com.hnas.trade.service.dto.DTOTradeRecord;

@Component("updateCoreTradeTaskService")
public class UpdateCoreTradeTaskServiceImpl implements UpdateCoreTradeTaskService{
	
	private static Log log = LogFactory.getLog(UpdateCoreTradeTaskServiceImpl.class);
	
	@Value("#{component['sycn_core_trade_record']}")
	private String sycnCordTradeRecord;

	@Autowired
	private TradeRecordService tradeRecordService;
	@Autowired
	private TradeRecordDao tradeRecordDao;
	@Autowired
	private AbnormalOrderService abnormalOrderService;
	@Autowired
	private IMrchService mrchService;
	@Autowired
	private AccountService accountService;
	@Autowired
	private HntEmployeeCardService hntEmployeeCardService;
	@Autowired
	private OrderService orderService;
	@Autowired
	private CardTrailService cardTrailService;
	@Autowired
	private AccECardService accECardService;
	
	@Override
	public void update() {
		//1、查询核心所有
		//2、查询本地
		//TODO 1查询本地当天的交易记录，2查询核心交易记录，3合并（如果当天不够条数，从历史中查当天以前的剩余条数）
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_MONTH, -1);
		List<TradeRecord> list = this.tradeRecordService.getAllByDate(null,null,null,DateUtil.dateTimeToString(cal.getTime()));
		//先查本地所有账户;如果有员工编号的，就去核心查；如果没有员工编号的，就去mysql上查询对应的卡号
		List<Account> accList = this.accountService.findAll();
		Map<String,List<DTOResultTransApp>> map = new HashMap<String,List<DTOResultTransApp>>();
		for(Account acc : accList){
			if(StringUtil.isEmpty(acc.getEmpId())){//无员工编号，虚拟卡用户
				//根据卡号去核心查询前一天联机交易记录
				AccECard vo = new AccECard();
				vo.setAccId(acc.getId());
				vo.setIsDeleted(false);
				List<AccECard> ecardList = this.accECardService.findByECard(vo);
				if(ecardList != null && ecardList.size() > 0) {
					for(AccECard accECard : ecardList) {
						List<DTOResultTransApp> tempList = getTradeByCardNo(accECard.getCardNo(), DateUtil.dateToString1(cal.getTime()));
						if(tempList != null && tempList.size() > 0){
							map.put(acc.getId(),tempList);
						}
					}
				}
			}else{//有员工编号，海贝用户
				//根据员工编号查询所有卡号，然后根据卡号查询前一天联机交易记录
				List<HntEmployeeCard> cardList = this.hntEmployeeCardService.getCardList(acc.getEmpId());
				if(cardList != null && cardList.size() > 0){
					List<DTOResultTransApp> tempList = new ArrayList<DTOResultTransApp>();
					for(HntEmployeeCard c : cardList){
						//根据卡号去核心查询前一天联机交易记录
						List<DTOResultTransApp> tlist = getTradeByCardNo(c.getCARD_NO(), DateUtil.dateToString1(cal.getTime()));
						if(tlist != null && tlist.size() > 0){
							tempList.addAll(tlist);
						}
					}
					if(tempList != null && tempList.size() > 0){
						map.put(acc.getId(),tempList);
					}
				}
			}
		}
		//TODO 合并
		Map<String,TradeRecord> tempMap = new HashMap<String,TradeRecord>(); 
		for(TradeRecord tr : list){
			if(StringUtil.isNotEmpty(tr.getTradeSno() )){
				tempMap.put(tr.getTradeSno(), tr);
			}
		}
		for(String key : map.keySet()){
			List<DTOResultTransApp> tempList = map.get(key);
			for(DTOResultTransApp dto : tempList){
				if(tempMap.containsKey(dto.getTRAN_SNO())){
					continue;
				}
				OrderType orderType = OrderType.getByCore(dto.getTRAN_TYPE(), dto.getTRAN_SUB_TYPE());
				DTOOrder orderDto = new DTOOrder();
				orderDto.setAccId(key);
				//TODO 如果是运营充值，需要判断该卡，在那个交易时间的所属账户id
				//TODO 判断是否是运营充值
				if("11".equals(dto.getTRAN_TYPE()) && "01".equals(dto.getTRAN_SUB_TYPE())) {
					//TODO 判断交易时间的账户id。判断交易时间之后是否有转赠记录，如果没有，账户id不变；如果有，取距离交易时间最近的转赠记录的赠送人id作为账户id
					List<CardTrail> cardTrailListOverTranDate = this.cardTrailService.listByCardAndDate(dto.getCARD_NO(),DateUtil.dateTimeToString(CommonUtils.getTranTime(dto.getTRAN_DATE(), dto.getTRAN_TIME())));
					if(cardTrailListOverTranDate == null || cardTrailListOverTranDate.size() <= 0) {
						orderDto.setAccId(key);
					}else {
						orderDto.setAccId(cardTrailListOverTranDate.get(0).getSendAccId());
					}
				}
//				orderDto.setAccName(accName);
//				orderDto.setAfterTradeBalance(afterTradeBalance);
				orderDto.setBeforeTradeBalance(dto.getCARD_BALANCE());
//				orderDto.setCancelTime(cancelTime);
				orderDto.setCardNo(dto.getCARD_NO());
//				orderDto.setCommidityId(commidityId);
//				orderDto.setCommidityName(commidityName);
//				orderDto.setCommidityType(commidityType);
				orderDto.setCoreTradeType(dto.getTRAN_TYPE());
				orderDto.setCoreTradeSubType(dto.getTRAN_SUB_TYPE());
				orderDto.setCreateTime(DateUtil.dateTimeToString(CommonUtils.getTranTime(dto.getTRAN_DATE(), dto.getTRAN_TIME())));
//				orderDto.setCreator(creator);
				orderDto.setId(CommonUtils.getUUID());
				orderDto.setIsOpTran(dto.getIS_OP_TRAN());
				orderDto.setMobilePhone(dto.getMOBILE_PHONE());
				orderDto.setMrchId(dto.getMRCH_ID());
				orderDto.setMrchName(dto.getTRAN_MRCH());
//				orderDto.setMrchType("");
				orderDto.setNeedPay(Math.abs(Double.valueOf(dto.getTRAN_VALUE()).longValue()));
				orderDto.setOpProductId(dto.getOP_PRODUCT_ID());
				orderDto.setOpProductType(dto.getOP_PRODUCT_TYPE());
				orderDto.setOpTelecomType(dto.getOP_TELECOM_TYPE());
				orderDto.setOpTranStatus(dto.getORDER_STATUS());
				orderDto.setOrderType(orderType == null?null:orderType.getType());
				orderDto.setOrderParentType(orderType == null?null:orderType.getParentType());
				orderDto.setOrderTypeName(orderType==null?null:OrderType.getOrderTypeName(orderType.getType()));
				orderDto.setPayEndTime(DateUtil.dateTimeToString(CommonUtils.getTranTime(dto.getTRAN_DATE(), dto.getTRAN_TIME())));
//				orderDto.setPayment(PaymentType.);//TODO
				orderDto.setRechChannel(dto.getRECH_CHANNEL());
				orderDto.setPayStatus(PayStatus.Payed.getStatus());
				orderDto.setOrderStatus(OrderStatus.Payed.getStatus());
//				orderDto.setPsamId("");
//				orderDto.setQrcodeNo("");
				orderDto.setRealPay(Math.abs(Double.valueOf(dto.getTRAN_AMT()).longValue()));
				orderDto.setRemark("同步交易记录生成");
				orderDto.setSubId(dto.getPAYMENT());
				orderDto.setSwiftNumber("");
				orderDto.setTermNo(dto.getEQP_ID());
				orderDto.setTradeEndTime(DateUtil.dateTimeToString(CommonUtils.getTranTime(dto.getTRAN_DATE(), dto.getTRAN_TIME())));
				orderDto.setOrderNo(dto.getTRAN_SNO());
				orderDto.setTradeSno(dto.getTRAN_SNO());
				orderDto.setTradeType(TradeType.APP.getType());
//				orderDto.setUpdater();
				orderDto.setUpdateTime(DateUtil.dateTimeToString(CommonUtils.getTranTime(dto.getTRAN_DATE(), dto.getTRAN_TIME())));
				try {
					this.orderService.saveOrUpdate(orderDto);
					System.out.println("插入成功："+orderDto.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				DTOTradeRecord trDto = new DTOTradeRecord();
				BeanUtils.copyProperties(orderDto, trDto);
				trDto.setId(CommonUtils.getUUID());
				try {
					this.tradeRecordService.saveOrUpdate(trDto);
					System.out.println("插入成功2："+trDto.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private List<DTOResultTransApp> getTradeByCardNo(String cardNo,String date){
		DTOSearchTrans dtoSearchTrans = new DTOSearchTrans();
		dtoSearchTrans.setCardNo(cardNo);
		dtoSearchTrans.setEndDate(date);
		dtoSearchTrans.setEndPage(null);
		dtoSearchTrans.setStartDate(date);
		dtoSearchTrans.setStartPage(null);
		dtoSearchTrans.setSubCode("224102,224101,224103");
		dtoSearchTrans.setTranState("01");
		dtoSearchTrans.setTranType(null);
		return this.mrchService.searchTransAppNew(dtoSearchTrans);
	}
	
	
	
	private List<DTOResultTransApp> getTradeByCardNo(String cardNo,String startDate,String endDate){
		DTOSearchTrans dtoSearchTrans = new DTOSearchTrans();
		dtoSearchTrans.setCardNo(cardNo);
		dtoSearchTrans.setEndDate(endDate);
		dtoSearchTrans.setEndPage(null);
		dtoSearchTrans.setStartDate(startDate);
		dtoSearchTrans.setStartPage(null);
		dtoSearchTrans.setSubCode("224102,224101,224103");
		dtoSearchTrans.setTranState("01,02,03,04");
		dtoSearchTrans.setTranType(null);
		return this.mrchService.searchTransAppNew(dtoSearchTrans);
	}
	
	/**
	 * 数据迁移查询旧版本海贝APP数据
	 * @param cardNo
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	private List<DTOResultTransApp> getTradeByOld(String cardNo,String startDate,String endDate){
		DTOSearchTrans dtoSearchTrans = new DTOSearchTrans();
		dtoSearchTrans.setCardNo(cardNo);
		dtoSearchTrans.setEndDate(endDate);
		dtoSearchTrans.setEndPage(null);
		dtoSearchTrans.setStartDate(startDate);
		dtoSearchTrans.setStartPage(null);
		dtoSearchTrans.setSubCode("224102,224101,224103");
		dtoSearchTrans.setTranState("01,02,03,04");
		dtoSearchTrans.setTranType(null);
		return this.mrchService.searchTransAppNew3(dtoSearchTrans);
	}
	
	private List<String> allCardNos = new ArrayList<String>();//cards 记录所有卡号
	private List<String> tempCards = new ArrayList<String>();//
	private List<String> abnormalTradeSno = new ArrayList<String>();//cards 记录所有卡号
	private Map<String,String> cardNoMap = new HashMap<String,String>();// cardNo,accountId 记录所有“卡号-账户id” 键直对
	private int normalSyncNum = 0;
	private int abNormalSyncNum = 0;
	private int abSearchNum = 0;
	
	

	@Override
	public String SyncCoreTranOrderRecord(String startDate, String endDate) {
		String sendData = "startDate:"+startDate+",endDate:"+endDate;
		DTOResult dtoResult = new DTOResult();
		String operation = "同步核心交易记录";
		String operationDate = DateUtil.dateToString(new Date());
		normalSyncNum = 0;
		abNormalSyncNum = 0;
		try {
			log.info(" 开始 "+operation+"!!!!");
			long beginTime = System.currentTimeMillis();
			String initResult = initSycnTradeInfo(dtoResult);
			log.info("初始化所有交易信息耗时:"+(System.currentTimeMillis()-beginTime));
			if(!ResultCode.SUCCESS.equals(initResult)){
				return initResult;
			}
			// 3.做每次去处理这么多条数据
			int everyTimeSycnNum = Integer.parseInt(sycnCordTradeRecord);
			log.info("每次约定批量处理:"+everyTimeSycnNum+"条！");
			// 查询本地当天所有正常交易记录
			List<String> tradeRecords = tradeRecordDao.findAllTradeSnoByDate(startDate, endDate);
			if(null!=tradeRecords&&tradeRecords.size()>0){
				log.info("本地"+startDate+"-"+endDate+"所有正常交易记录条数:"+tradeRecords.size());
			}else{
				log.info("本地"+startDate+"-"+endDate+"所有正常交易记录条数:0");
			}
			// 查询本地当天异常交易信息
			List<String> abnormalTransRecord = abnormalOrderService.findAllAbnormalTranSnoByDate(startDate, endDate);
			if(null!=abnormalTransRecord&&abnormalTransRecord.size()>0){
				log.info("本地"+startDate+"-"+endDate+"异常交易信息条数:"+abnormalTransRecord.size());
			}else{
				log.info("本地"+startDate+"-"+endDate+"异常交易信息条数:0");
			}
			//递归批量处理
			log.info("开始递归处理批量数据!!!!");
			long bathTime = new Date().getTime();
			recursionDoRecord(startDate, endDate, everyTimeSycnNum, tradeRecords,abnormalTransRecord);
			log.info("结束递归处理:耗时====》"+(System.currentTimeMillis()-bathTime));
			//耗时
			long timeConsuming = System.currentTimeMillis()-beginTime;
			log.info("结束 "+operation+"!!!!");
			String success = operationDate+operation+",同步数据开始时间:"+startDate+",结束时间:"+endDate+",耗时:"+timeConsuming+",处理总条数："
			                +(normalSyncNum+abNormalSyncNum)+"条！其中正常条数有:"+normalSyncNum+"条，异常条数："+abNormalSyncNum+"条";
			return CommonUtils.createResult(dtoResult, ResultCode.SUCCESS, success);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(DateUtil.dateTimeToString(new Date()) + ""+",请求数据:入参为:" + sendData + "  异常:" + e);
			return CommonUtils.createResult(dtoResult, ResultCode.ERRCODE_60004, null);
		} finally {
			log.info(DateUtil.dateTimeToString(new Date()) + "同步核心交易订单数据"+ ",请求数据:入参为:" + sendData + "  返回参数:" + dtoResult);
		}
	}
	
	@Override
	public String SyncCoreTranOrderRecord2(String startDate, String endDate) {
		String sendData = "startDate:"+startDate+",endDate:"+endDate;
		DTOResult dtoResult = new DTOResult();
		String operation = "同步核心交易记录";
		String operationDate = DateUtil.dateToString(new Date());
		normalSyncNum = 0;
		abNormalSyncNum = 0;
		int allNormal = 0;
		int allAbNormal = 0;
		try {
			log.info(" 开始 "+operation+"!!!!");
			long beginTime = System.currentTimeMillis();
			String initResult = initSycnTradeInfo(dtoResult);
			log.info("初始化所有交易信息耗时:"+(System.currentTimeMillis()-beginTime));
			if(!ResultCode.SUCCESS.equals(initResult)){
				return initResult;
			}
			
			tempCards.addAll(allCardNos);
			Calendar startCal = Calendar.getInstance();
			startCal.setTime(DateUtil.stringToDate(startDate, "yyyyMMdd"));
			Calendar endCal = Calendar.getInstance();
			endCal.setTime(DateUtil.stringToDate(endDate, "yyyyMMdd"));
			endCal.add(Calendar.DAY_OF_YEAR, 1);
			String success = "";
			String tempStartDate = null;
			while(endCal.after(startCal)){
				tempStartDate = DateUtil.dateToString(startCal.getTime(),"yyyyMMdd");
				// 3.做每次去处理这么多条数据
				int everyTimeSycnNum = Integer.parseInt(sycnCordTradeRecord);
				log.info("每次约定批量处理:"+everyTimeSycnNum+"条！");
				// 查询本地当天所有正常交易记录
				List<String> tradeRecords = tradeRecordDao.findAllTradeSnoByDate(tempStartDate, tempStartDate);
				if(null!=tradeRecords&&tradeRecords.size()>0){
					log.info("本地"+tempStartDate+"-"+tempStartDate+"所有正常交易记录条数:"+tradeRecords.size());
				}else{
					log.info("本地"+tempStartDate+"-"+tempStartDate+"所有正常交易记录条数:0");
				}
				// 查询本地当天异常交易信息
				List<String> abnormalTransRecord = abnormalOrderService.findAllAbnormalTranSnoByDate(tempStartDate, tempStartDate);
				if(null!=abnormalTransRecord&&abnormalTransRecord.size()>0){
					log.info("本地"+tempStartDate+"-"+tempStartDate+"异常交易信息条数:"+abnormalTransRecord.size());
				}else{
					log.info("本地"+tempStartDate+"-"+tempStartDate+"异常交易信息条数:0");
				}
				//递归批量处理
				log.info("开始递归处理批量数据!!!!");
				long bathTime = new Date().getTime();
				recursionDoRecord(tempStartDate, tempStartDate, everyTimeSycnNum, tradeRecords,abnormalTransRecord);
				log.info("结束递归处理:耗时====》"+(System.currentTimeMillis()-bathTime));
				//耗时
				long timeConsuming = System.currentTimeMillis()-beginTime;
				log.info("结束 "+operation+"!!!!");
				success = operationDate+operation+",同步数据开始时间:"+tempStartDate+",结束时间:"+tempStartDate+",耗时:"+timeConsuming+",处理总条数："
				                +(normalSyncNum+abNormalSyncNum)+"条！其中正常条数有:"+normalSyncNum+"条，异常条数："+abNormalSyncNum+"条";
				System.out.println(success);
				allNormal+=normalSyncNum;
				allAbNormal+=abNormalSyncNum;
				normalSyncNum = 0;
				abNormalSyncNum = 0;
				startCal.add(Calendar.DAY_OF_YEAR, 1);
			}
			success+="本次同步所有条数："+(allNormal+allAbNormal)+",其中正常:"+allNormal+",异常:"+allAbNormal;
			return CommonUtils.createResult(dtoResult, ResultCode.SUCCESS, success);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(DateUtil.dateTimeToString(new Date()) + ""+",请求数据:入参为:" + sendData + "  异常:" + e);
			return CommonUtils.createResult(dtoResult, ResultCode.ERRCODE_60004, null);
		} finally {
			log.info(DateUtil.dateTimeToString(new Date()) + "同步核心交易订单数据"+ ",请求数据:入参为:" + sendData + "  返回参数:" + dtoResult);
		}
	}
	
	String kCards = "";//空卡
	String abOrderTypeCards = "";//异常卡类型
	String noInCards = "";//38 05
	int noINCardsNum = 0;
	int removeNum = 0;
	int abOrderTypeNum = 0;
	@Override
	public String SyncCoreTranOrderRecord3(String startDate,String endDate) {
		String sendData = "startDate:"+startDate+",endDate:"+endDate;
		DTOResult dtoResult = new DTOResult();
		String operation = "同步核心交易记录";
		String operationDate = DateUtil.dateToString(new Date());
		normalSyncNum = 0;
		abNormalSyncNum = 0;
		abSearchNum = 0;
		removeNum = 0;
		abOrderTypeNum = 0;
		kCards = "";//空卡
		abOrderTypeCards = "";//异常卡类型
		noInCards = "";//38 05
		try {
			log.info(" 开始初始化所有卡号信息!!!!");
			long beginTime = System.currentTimeMillis();
			String initResult = initSycnTradeInfo(dtoResult);
			log.info(" 结束初始化所有卡号信息!!!!");
			log.info(" 初始化所有卡号信息耗时:"+(System.currentTimeMillis()-beginTime));
			if(!ResultCode.SUCCESS.equals(initResult)){
				return initResult;
			}
			long beginSearchLocalTime = System.currentTimeMillis();
			log.info("开始查询本地正常和异常的交易记录：");
			// 查询本地当天所有正常交易记录
			List<String> tradeRecords = tradeRecordDao.findAllTradeSnoByDate(startDate, endDate);
			if(null!=tradeRecords&&tradeRecords.size()>0){
				log.info("本地"+startDate+"-"+endDate+"所有正常交易记录条数:"+tradeRecords.size());
			}else{
				log.info("本地"+startDate+"-"+endDate+"所有正常交易记录条数:0");
			}
			// 查询本地当天异常交易信息
			List<String> abnormalTransRecord = abnormalOrderService.findAllAbnormalTranSnoByDate(startDate, endDate);
			if(null!=abnormalTransRecord&&abnormalTransRecord.size()>0){
				log.info("本地"+startDate+"-"+endDate+"异常交易信息条数:"+abnormalTransRecord.size());
			}else{
				log.info("本地"+startDate+"-"+endDate+"异常交易信息条数:0");
			}
			long endSearchLocalTime = System.currentTimeMillis();
			log.info("结束查询本地正常和异常的交易记录：");
			log.info("结束查询本地正常和异常的交易记录耗时："+(endSearchLocalTime-beginSearchLocalTime));
			String cardNos = "";
			if(null!=allCardNos&&allCardNos.size()>0){
				for(int i=0;i<allCardNos.size();i++){
					if(i<allCardNos.size()-1){
						cardNos+=allCardNos.get(i)+",";
					}else{
						cardNos+=allCardNos.get(i);
					}
				}
			}else{
				log.info("同步没有卡号");
			}
			log.info("开始查询旧海贝APP所有的交易记录：");
			//查询旧版本所有交易记录
			long beginSearHBOld = System.currentTimeMillis();
			List<DTOResultTransApp> tempList = getTradeByOld(cardNos, startDate, endDate);
			log.info("结束查询旧海贝APP所有的交易记录：");
			long endSearHBOld = System.currentTimeMillis();
			log.info("查询旧海贝APP所有的交易记录耗时："+(endSearHBOld-beginSearHBOld));
			//针对正常的交易记录进行合并
			if(null!=tempList&&tempList.size()>0){
				log.info(startDate+"旧海贝APP所有的交易记录条数:"+tempList.size());
				Iterator<DTOResultTransApp> iterator = tempList.iterator();
				while(iterator.hasNext()){
					DTOResultTransApp it = iterator.next();
					   //正常交易记录比较
					   if(tradeRecords.contains(it.getTRAN_SNO())){
						  if(!TranState.Normal.getState().equals(it.getTRAN_STATE())){
							  tradeRecordService.deleteByTranSno(it.getTRAN_SNO());
							  System.out.println("删除流水1:"+it.getTRAN_SNO());
						  }
						  removeNum++;
						  iterator.remove();
						  continue;
						} 
						//异常交易记录比较
						if(abnormalTransRecord.contains(it.getTRAN_SNO())){
							 removeNum++;
							iterator.remove();
							continue;
						} 
						
						//不同步撤销38
					   if(CoreTradeType.LinkNetTrade_Cancel.getType().equals(it.getTRAN_TYPE())&&TranState.Normal.getState().equals(it.getTRAN_STATE())){
						   noINCardsNum++;
						   removeNum++;
						   noInCards+="'"+it.getCARD_NO()+"',";
						   iterator.remove();
						   continue;
					   }
					   //不同步撤销05
					   if(CoreTradeType.Core_Reject.getType().equals(it.getTRAN_TYPE())&&TranState.Normal.getState().equals(it.getTRAN_STATE())){
						   noINCardsNum++;
						   removeNum++;
						   noInCards+="'"+it.getCARD_NO()+"',";
						   iterator.remove();
						   continue;
					   }
					}
				}
			
			log.info("本次同步条数:"+tempList.size());
			//针对只存在核心的交易记录同步到本地
			if(tempList.size()>0){
				for(DTOResultTransApp transApp :tempList){
					if(StringUtil.isNotEmpty(transApp.getTRAN_STATE())){
						String accountId = cardNoMap.get(transApp.getCARD_NO());
						if(StringUtil.isNotEmpty(accountId)){
							//存储订单
							//saveOrderAndTradeRecord(transApp, accountId);
							try {
								saveOrderAndTradeRecord(transApp, cardNoMap.get(transApp.getCARD_NO()));
							} catch (Exception e) {
								e.printStackTrace();
								abOrderTypeNum++;
								abOrderTypeCards+=transApp.getTRAN_TYPE()+","+ transApp.getTRAN_SUB_TYPE()+","+transApp.getCARD_NO()+"==";
							}
						}else{
							abSearchNum++;
							kCards+="'"+transApp.getCARD_NO()+"',";
							//System.out.println("accountID为空："+transApp.getCARD_NO());
						}
					}
				}
				
			}
			//耗时
			long timeConsuming = System.currentTimeMillis()-beginTime;
			String success = operationDate+operation+",同步数据开始时间:"+startDate+",结束时间:"+endDate+",耗时:"+timeConsuming+",处理总条数："
	                +(normalSyncNum+abNormalSyncNum)+"条！其中正常条数有:"+normalSyncNum+"条，异常条数："+abNormalSyncNum+"条,空卡数:"+abSearchNum+",空卡卡号:"+kCards+",3805的卡数:"+noINCardsNum+",3805卡号:"+noInCards+",移除数量:"+ removeNum;
			return CommonUtils.createResult(dtoResult, ResultCode.SUCCESS, success);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(DateUtil.dateTimeToString(new Date()) + ""+",请求数据:入参为:" + sendData + "  异常:" + e);
			return CommonUtils.createResult(dtoResult, ResultCode.ERRCODE_60004, null);
		} finally {
			log.info(DateUtil.dateTimeToString(new Date()) + "同步核心交易订单数据"+ ",请求数据:入参为:" + sendData + "  返回参数:" + dtoResult);
		}
	}

	/**
	 * 递归处理
	 * @param startDate
	 * @param endDate
	 * @param everyTimeSycnNum
	 * @param tradeRecords
	 */
	private void recursionDoRecord(String startDate, String endDate, int everyTimeSycnNum,List<String> tradeRecords,List<String> abnormalTransRecord) {
		int length = 0;
		String cardNos = "";
		if(allCardNos.size()<everyTimeSycnNum){
			length = allCardNos.size();
			mapperToDoRecord(startDate, endDate, tradeRecords, length, cardNos,abnormalTransRecord);
			allCardNos.addAll(tempCards);
		}else{
			length = everyTimeSycnNum;
			mapperToDoRecord(startDate, endDate, tradeRecords, length, cardNos,abnormalTransRecord);
			//剩余数量大于每次处理条数，递归处理
			recursionDoRecord(startDate, endDate, everyTimeSycnNum, tradeRecords,abnormalTransRecord);
		}
	}

	
	private void mapperToDoRecord(String startDate, String endDate, List<String> tradeRecords, int length,String cardNos,List<String> abnormalTransRecord) {
		//1.配置卡号字符串         card1,card2,card3
		for(int i=0;i<length;i++){
			if(i<length-1){
				cardNos+=allCardNos.get(i)+",";
			}else{
				cardNos+=allCardNos.get(i);
			}
		}
		//2.处理一批卡号
		operationForCard(startDate, endDate, tradeRecords, cardNos,abnormalTransRecord);
		//3.移除内存中的卡号
		for(int i=0;i<length;i++){
			allCardNos.remove(0);
		}
		
	}

	/**
	 * 处理一批卡号
	 * @param startDate
	 * @param endDate
	 * @param tradeRecords
	 * @param cardNos
	 */
	private void operationForCard(String startDate, String endDate, List<String> tradeRecords, String cardNos,List<String> abnormalTransRecord) {
		//批量查找核心交易记录
		List<DTOResultTransApp> tempList = getTradeByCardNo(cardNos, startDate, endDate);
		//针对正常的交易记录进行合并
		if(null!=tempList&&tempList.size()>0){
			log.info(startDate+"获取核心数据条数:"+tempList.size());
			Iterator<DTOResultTransApp> iterator = tempList.iterator();
			while(iterator.hasNext()){
				DTOResultTransApp it = iterator.next();
				   //正常交易记录比较
				   if(tradeRecords.contains(it.getTRAN_SNO())){
					  if(!TranState.Normal.getState().equals(it.getTRAN_STATE())){
						  tradeRecordService.deleteByTranSno(it.getTRAN_SNO());
						  System.out.println("删除流水1:"+it.getTRAN_SNO());
					  }
					  iterator.remove();
					  continue;
					} 
					//异常交易记录比较
					if(abnormalTransRecord.contains(it.getTRAN_SNO())){
						iterator.remove();
						continue;
					} 
					
					//不同步撤销38
				   if(CoreTradeType.LinkNetTrade_Cancel.getType().equals(it.getTRAN_TYPE())&&TranState.Normal.getState().equals(it.getTRAN_STATE())){
					   iterator.remove();
					   continue;
				   }
				   //不同步撤销05
				   if(CoreTradeType.Core_Reject.getType().equals(it.getTRAN_TYPE())&&TranState.Normal.getState().equals(it.getTRAN_STATE())){
					   iterator.remove();
					   continue;
				   }
				    
				
				}
			}
		
		log.info("本次同步条数:"+tempList.size());
		//针对只存在核心的交易记录同步到本地
		if(tempList.size()>0){
			for(DTOResultTransApp transApp :tempList){
				if(StringUtil.isNotEmpty(transApp.getTRAN_STATE())){
					//存储订单
					try {
						saveOrderAndTradeRecord(transApp, cardNoMap.get(transApp.getCARD_NO()));
					} catch (Exception e) {
						e.printStackTrace();
					}
					
				}
			}
			
		}
	}

	private String initSycnTradeInfo(DTOResult dtoResult) {
		//置空
		allCardNos = new ArrayList<String>();
		cardNoMap = new HashMap<String, String>();
		tempCards = new ArrayList<String>();
		// 1.找出所有用户
		List<Account> accList = this.accountService.findAll();
		if(null==accList||accList.size()==0){
			log.error("查找所有用户为空");
			return CommonUtils.createResult(dtoResult, ResultCode.ERRCODE_10003, "查找所有用户为空");
		}
		log.info("本地用户总量为:"+accList.size());
		// 2.根据账户查找所有卡
		for(Account account : accList){
			//  2.1 读取海航员工原来所有卡号
			if(StringUtil.isNotEmpty(account.getEmpId())){
				List<HntEmployeeCard> hntCardList = this.hntEmployeeCardService.getCardList(account.getEmpId());
				if(null!= hntCardList&&hntCardList.size()>0){
					for(HntEmployeeCard cardObj : hntCardList){
						if(!allCardNos.contains(cardObj.getCARD_NO())){
							allCardNos.add(cardObj.getCARD_NO());
							cardNoMap.put(cardObj.getCARD_NO(), account.getId());
						}
					}
				}
			}else{
				// 2.3 找所有的电子卡
				AccECard vo = new AccECard();
				vo.setIsDeleted(false);
				vo.setAccId(account.getId());
				List<AccECard> ecardList = this.accECardService.findByECard(vo);
				if(ecardList != null && ecardList.size() > 0) {
					for(AccECard ec : ecardList) {
						allCardNos.add(ec.getCardNo());
						cardNoMap.put(ec.getCardNo(), account.getId());
					}
				}
			}
		}
		
		System.out.println("卡号总数:"+allCardNos.size());
		return ResultCode.SUCCESS;
		
	}
	
	public static void main(String[] args) throws ParseException {
		//同步前一天数据
				/*Calendar calendar = getBeforeDay(Calendar.getInstance());
				int year = calendar.get(Calendar.YEAR);
				int mouth = calendar.get(Calendar.MONTH)+1;
				int yesterday = calendar.get(Calendar.DATE);
				String synDate = "";
				if(mouth<10){
					synDate+=year+"0"+mouth+yesterday;
				}else{
					synDate+=year+mouth+yesterday;
				}
				 
				System.out.println("同步日期:"+synDate);*/
		
		Calendar cal1 = Calendar.getInstance();
		Calendar cal2 = Calendar.getInstance();
		Date date1 = DateUtil.stringToDate("20170928", "yyyyMMdd");
		Date date2 = DateUtil.stringToDate("20170930", "yyyyMMdd");
		cal1.setTime(date1);
		cal2.setTime(date2);
		cal2.add(Calendar.DAY_OF_YEAR, 1);
		while(cal2.after(cal1)){
			System.out.println(DateUtil.dateToString(cal1.getTime()));
			cal1.add(Calendar.DAY_OF_YEAR, 1);
		}
	}
	
	public void saveOrderAndTradeRecord(DTOResultTransApp dto,String accountId){
		OrderType orderType = OrderType.getByCore(dto.getTRAN_TYPE(), dto.getTRAN_SUB_TYPE());
		//System.out.println(dto.getTRAN_TYPE()+","+dto.getTRAN_SUB_TYPE()+orderType.getDescription()+","+dto.getTRAN_STATE()+",余额："+dto.getCARD_BALANCE());
		if(null != orderType){
			if(OrderType.Reject.getType().equals(orderType.getType())){
				dto.setTRAN_STATE(TranState.Returned.getState());
			}
			
			if(OrderType.Cancel.getType().equals(orderType.getType())){
				dto.setTRAN_STATE(TranState.Rescinded.getState());
			}
			
			if(OrderType.CZ.getType().equals(orderType.getType())){
				dto.setTRAN_STATE(TranState.Reversed.getState());
			}
			//System.out.println(dto.getTRAN_TYPE()+","+dto.getTRAN_SUB_TYPE()+orderType.getDescription()+","+dto.getTRAN_STATE());
			String createTime = DateUtil.dateTimeToString(new Date());
			
			DTOOrder orderDto = new DTOOrder();
			orderDto.setAccId(accountId);
			//TODO 如果是运营充值，需要判断该卡，在那个交易时间的所属账户id
			//TODO 判断是否是运营充值
			if("11".equals(dto.getTRAN_TYPE()) && "01".equals(dto.getTRAN_SUB_TYPE())) {
				//TODO 判断交易时间的账户id。判断交易时间之后是否有转赠记录，如果没有，账户id不变；如果有，取距离交易时间最近的转赠记录的赠送人id作为账户id
				List<CardTrail> cardTrailListOverTranDate = this.cardTrailService.listByCardAndDate(dto.getCARD_NO(),DateUtil.dateTimeToString(CommonUtils.getTranTime(dto.getTRAN_DATE(), dto.getTRAN_TIME())));
				if(cardTrailListOverTranDate == null || cardTrailListOverTranDate.size() <= 0) {
					orderDto.setAccId(accountId);
				}else {
					orderDto.setAccId(cardTrailListOverTranDate.get(0).getSendAccId());
				}
			}
			
			orderDto.setCardNo(dto.getCARD_NO());
			orderDto.setCoreTradeType(dto.getTRAN_TYPE());
			orderDto.setCoreTradeSubType(dto.getTRAN_SUB_TYPE());
			orderDto.setCreateTime(createTime);
			orderDto.setId(CommonUtils.getUUID());
			orderDto.setIsOpTran(dto.getIS_OP_TRAN());
			orderDto.setMobilePhone(dto.getMOBILE_PHONE());
			orderDto.setMrchId(dto.getMRCH_ID());
			orderDto.setMrchName(dto.getTRAN_MRCH());
			orderDto.setNeedPay(Double.valueOf(dto.getTRAN_VALUE()).longValue());
			orderDto.setOpProductId(dto.getOP_PRODUCT_ID());
			orderDto.setOpProductType(dto.getOP_PRODUCT_TYPE());
			orderDto.setOpTelecomType(dto.getOP_TELECOM_TYPE());
			orderDto.setOpTranStatus(dto.getORDER_STATUS());
			orderDto.setOrderType(orderType == null?null:orderType.getType());
			orderDto.setOrderParentType(orderType == null?null:orderType.getParentType());
			orderDto.setOrderTypeName(orderType==null?null:OrderType.getOrderTypeName(orderType.getType()));
			orderDto.setPayEndTime(DateUtil.dateTimeToString(CommonUtils.getTranTime(dto.getTRAN_DATE(), dto.getTRAN_TIME())));
			orderDto.setRechChannel(dto.getRECH_CHANNEL());
			orderDto.setPayStatus(PayStatus.Payed.getStatus());
			orderDto.setOrderStatus(OrderStatus.Payed.getStatus());
			orderDto.setRealPay(Double.valueOf(dto.getTRAN_AMT()).longValue());
			orderDto.setRemark("同步交易记录生成");
			orderDto.setSubId(dto.getPAYMENT());
			orderDto.setSwiftNumber("");
			orderDto.setTermNo(dto.getEQP_ID());
			orderDto.setTradeEndTime(DateUtil.dateTimeToString(CommonUtils.getTranTime(dto.getTRAN_DATE(), dto.getTRAN_TIME())));
			orderDto.setOrderNo(dto.getTRAN_SNO());
			orderDto.setTradeSno(dto.getTRAN_SNO());
			orderDto.setTradeType(TradeType.APP.getType());
			orderDto.setUpdateTime(createTime);
			orderDto.setIsDeleted(true);
			if(StringUtil.isNotEmpty(dto.getCARD_BALANCE())){
				orderDto.setAfterTradeBalance(String.valueOf(Double.parseDouble(dto.getCARD_BALANCE())*100));
			}
			//正常订单
			if(TranState.Normal.getState().equals(dto.getTRAN_STATE())){
				try {
					this.orderService.saveOrUpdate(orderDto);
					//log.info("插入订单成功："+orderDto.getId());
				} catch (Exception e) {
					e.printStackTrace();
				}
				DTOTradeRecord trDto = new DTOTradeRecord();
				BeanUtils.copyProperties(orderDto, trDto);
				trDto.setId(CommonUtils.getUUID());
				try {
					this.tradeRecordService.saveOrUpdate(trDto);
//					log.info("插入交易记录成功："+trDto.getId());
//					log.info("保存当前流水号为："+dto.getTRAN_SNO()+" 正常记录！！");
					normalSyncNum++;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}else{//异常订单
				try {
					AbnormalOrder obj = new AbnormalOrder();
					BeanUtils.copyProperties(orderDto, obj);
					obj.setTranStatus(dto.getTRAN_STATE());
					obj.setId(CommonUtils.getUUID());
					abnormalOrderService.saveOrUpdate(obj);
//					log.info("保存当前流水号为："+dto.getTRAN_SNO()+" 异常记录！！");
					abNormalSyncNum++;
				} catch (Exception e) {
					e.printStackTrace();
					log.error("保存 异常订单异常！");
				}
			}
		}
		
	}

	@Override
	public void doSynCoreMethod() {
		//同步前一天数据
		Calendar   cal   =   Calendar.getInstance();
		cal.add(Calendar.DATE,-1);
		String synDate = new SimpleDateFormat( "yyyyMMdd").format(cal.getTime());
		System.out.println("同步日期:"+synDate);
		this.SyncCoreTranOrderRecord(synDate, synDate);
	}
	
	private static Calendar getBeforeDay(Calendar cl) {  
        int day = cl.get(Calendar.DATE);  
        cl.set(Calendar.DATE, day - 1);  
        return cl;  
    }

	@Override
	public List<DTOResultTransApp> getTradeByCardNo1(String cardNo, String startDate, String endDate) {
		return this.getTradeByCardNo(cardNo, startDate, endDate);
	}

	@Override
	public void getTradeByOld3(String cardNos, String startDate, String endDate) {
		this.getTradeByOld(cardNos, startDate, endDate);
		
	} 
	
}
